﻿using System.Collections;

namespace Newtonsoft.Json
{
    public class CompositeFormatterJsonConverter : JsonConverter
    {
        private readonly IAdditionDataFormatter _additionDataFormatter;
        private readonly JsonConverter _converter;
        public CompositeFormatterJsonConverter(IAdditionDataFormatter additionDataFormatter, JsonConverter converter = null)
        {
            _converter = converter;
            _additionDataFormatter = additionDataFormatter;
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (_converter != null)
            {
                _converter.WriteJson(writer, value, serializer);
                writeAdditionDataJson();
                return;
            }
            else
            {
                if (value == null)
                {
                    writer.WriteNull();
                    writeAdditionDataJson();
                    return;
                }

                if (!(value is byte[]) && !(value is string) && value is IEnumerable arr)
                {
                    writer.WriteStartArray();
                    foreach (var v in arr)
                    {
                        writer.WriteValue(v);
                    }

                    writer.WriteEndArray();
                }
                else
                {
                    writer.WriteValue(value);
                }
                writeAdditionDataJson();
            }

            void writeAdditionDataJson()
            {
                WriteAddtionJson(writer, value);
            }

        }

        protected void WriteAddtionJson(JsonWriter writer, object value)
        {
            if (_additionDataFormatter == null) return;

            string path = writer.Path;
            var index = writer.Path.LastIndexOf('.');
            if (index > 0 && index + 1 < path.Length)
            {
                path = writer.Path.Substring(index + 1);
            }

            var name = _additionDataFormatter.FormatName(writer.Path);
            if (string.IsNullOrWhiteSpace(name) || name == path) return;

            var exValue = _additionDataFormatter.FormatValue(value);

            writer.WritePropertyName(name);

            if (exValue == null)
            {
                writer.WriteNull();
                return;
            }

            if (!(exValue is byte[]) && !(exValue is string) && exValue is IEnumerable arr)
            {
                writer.WriteStartArray();
                foreach (var v in arr)
                {
                    writer.WriteValue(v);
                }

                writer.WriteEndArray();
            }
            else
            {
                writer.WriteValue(exValue);
            }
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (_converter != null)
            {
                return _converter.ReadJson(reader, objectType, existingValue, serializer);
            }

            return reader.Value;
        }

        public override bool CanConvert(Type objectType)
        {
            if (_converter != null) return _converter.CanConvert(objectType);

            return true;
        }
    }
}
